Introduction
A mixed model with random effects was chosen for this multifactor experiment, and analyzed using the limma package in R. This package implements a linear modeling approach and empirical Bayes statistics. The limma package with the voom method estimates the mean-variance relationship of the log-counts, generates a precision weight for each observation and enters these into the limma empirical Bayes analysis pipeline.
In this model, clade (levels = Clade1, Clade2, Clade3), physiology (levels = Marine, Freshwater), and experimental condition (levels = 15ppt, 0.2ppt) are fixed effects while species (levels = 14) is considered a random effect.
The raw counts file, generated with NumReads from the salmon (version 0.12.0) quantification tool and summarized with the tximport Bioconductor package (version 1.10.1) in R, can be downloaded from an osf repository with this link, then imported into the R framework.
Samples from species with low numbers of replicates were dropped from the raw counts table (F. zebrinus, F. nottii, F. sciadicus). The raw counts table has the following dimensions (genes x samples).
#dim(design)
#[1] 5 81
dim(counts)
[1] 30466 81
Sample Design Matrix
A matrix was generated using the following model with fixed effects:
~0 + physiology*condition*clade
The random effect of species will be taken into account later.
Filtering and Normalization
Genes with low expression across samples were dropped from the analysis using a conservative approach. The function filterByExpr was used on the raw counts matrix. For each condition_physiology group (regardless of species), each sample must have a minium count of 10, and a group minium total count of 100. This reduced the counts table to the following dimensions (genes x samples):
gene.names<-rownames(counts)
counts<-as.matrix(as.data.frame(sapply(counts, as.numeric)))
rownames(counts)<-gene.names
#class(counts)
keep<-filterByExpr(counts,design = design,group=condition_physiology,min.count = 10, min.total.count = 100)
counts.filt <- counts[keep,]
dim(counts.filt)
#write.csv(counts.filt,"../../../21k_counts_filt_30April2019.csv")
Genes of Interest
After filtration, we check the counts matrix for the presence of several genes of interest. These genes have demonstrated responsiveness to salinity change from past studies.
| zymogen granule membrane protein 16 |
Funhe2EKm029929 |
ENSFHEP00000007220.1 |
|
| zymogen granule membrane protein 16 |
Funhe2EKm029931 |
ENSFHEP00000025841 |
|
| solute carrier family 12 member 3-like (removed) |
Funhe2EKm006896 |
ENSFHEP00000009214 |
|
| chloride channel, voltage-sensitive 2 (clcn2), transcript variant X2 (removed) |
Funhe2EKm024148 |
ENSFHEP00000019510 |
|
| ATP-sensitive inward rectifier potassium channel 1 |
Funhe2EKm001965 |
ENSFHEP00000015383 |
|
| inward rectifier potassium channel 2 |
Funhe2EKm023780 |
ENSFHEP00000009753 |
|
| aquaporin-3 |
|
ENSFHEP00000006725 |
|
| cftr |
Funhe2EKm024501 |
ENSFHEP00000008393 |
|
| polyamine-modulated factor 1-like |
Funhe2EKm031049 |
ENSFHEP00000013324 |
|
| sodium/potassium/calcium exchanger 2 |
Funhe2EKm025497 |
ENSFHEP00000034177 |
|
| septin-2B isoform X2 |
|
ENSFHEP00000015765 |
|
| CLOCK-interacting pacemaker-like |
Funhe2EKm026846 |
ENSFHEP00000017303 |
|
| vasopressin V2 receptor-like |
Funhe2EKm026721 |
ENSFHEP00000000036 |
|
| sodium/potassium-transporting ATPase subunit beta-1-interacting protein 1 |
Funhe2EKm001174 |
ENSFHEP00000031108 |
|
| septin-2 |
Funhe2EKm012182 |
ENSFHEP00000016853 |
|
| otopetrin-2 |
Funhe2EKm035427 |
ENSFHEP00000026411 |
|
| claudin 8 |
Funhe2EKm037718 |
ENSFHEP00000006282 |
|
| claudin 4 |
Funhe2EKm007149 |
ENSFHEP00000003908 |
|
If the Ensembl ID displays below, the gene is present in the whole data set and has not been filtered.
# ---------------------------
# Andrew Whitehead's genes of interest:
# ---------------------------
# zymogen granule membrane protein 16
# Funhe2EKm029929
# ENSFHEP00000007220.1
countsfilt <- counts.filt
countsfilt$row <- rownames(countsfilt)
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000007220.1"]
goi
# zymogen granule membrane protein 16
# Funhe2EKm029931
# ENSFHEP00000025841
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000025841"]
goi
# solute carrier family 12 member 3-like (removed)
# Funhe2EKm006896
# ENSFHEP00000009214
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000009214"]
goi
# chloride channel, voltage-sensitive 2 (clcn2), transcript variant X2 (removed)
# Funhe2EKm024148
# ENSFHEP00000019510
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000019510"]
goi
# ATP-sensitive inward rectifier potassium channel 1
# Funhe2EKm001965
# ENSFHEP00000015383
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000015383"]
goi
# inward rectifier potassium channel 2
# Funhe2EKm023780
# ENSFHEP00000009753
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000009753"]
# --------------------------------
# other salinity genes of interest
# --------------------------------
# ============================================
# aquaporin-3
# ENSFHEP00000006725
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000006725"]
goi
# cftr
# Funhe2EKm024501
# ENSFHEP00000008393
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000008393"]
goi
# polyamine-modulated factor 1-like
# Funhe2EKm031049
# ENSFHEP00000013324
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000013324"]
goi
# sodium/potassium/calcium exchanger 2
# ENSFHEP00000034177
# Funhe2EKm025497
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000034177"]
goi
# septin-2B isoform X2
# ENSFHEP00000015765
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000015765"]
goi
# CLOCK-interacting pacemaker-like
# ENSFHEP00000017303
# Funhe2EKm026846
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000017303"]
goi
# vasopressin V2 receptor-like
# Funhe2EKm026721
# ENSFHEP00000000036
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000000036"]
goi
# sodium/potassium-transporting ATPase subunit beta-1-interacting protein 1
# ENSFHEP00000031108
# Funhe2EKm001174
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000031108"]
goi
# septin-2
# Funhe2EKm012182
# ENSFHEP00000016853
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000016853"]
goi
# otopetrin-2
# Funhe2EKm035427
# ENSFHEP00000026411
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000026411"]
goi
# claudin 8
# Funhe2EKm037718
# ENSFHEP00000006282
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000006282"]
goi
# claudin 4
# ENSFHEP00000003908
# Funhe2EKm007149
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000003908"]
goi
all_goi<-c("ENSFHEP00000007220.1","ENSFHEP00000025841","ENSFHEP00000019510",
"ENSFHEP00000015383","ENSFHEP00000009753","ENSFHEP00000006725","ENSFHEP00000008393",
"ENSFHEP00000013324","ENSFHEP00000001609","ENSFHEP00000013324","ENSFHEP00000034177",
"ENSFHEP00000015765","ENSFHEP00000017303","ENSFHEP00000000036","ENSFHEP00000031108",
"ENSFHEP00000016853","ENSFHEP00000003908")
Exploratory Plots
Log counts before normalization:
# log counts before DE
boxplot(log(counts.filt+1), las = 2, main = "")
Log counts after cpm normalization
# ---------------
# DE analysis
# ---------------
genes = DGEList(count = counts.filt, group = condition_physiology_clade)
genes = calcNormFactors( genes )
# write normalized counts
dir <- "~/Documents/UCDavis/Whitehead/"
tmp <- as.data.frame(cpm(genes))
tmp$Ensembl <- rownames(tmp)
tmp <- dplyr::select(tmp, Ensembl, everything())
write.csv(tmp, file = file.path(dir, "normalized_counts.csv"), quote = F, row.names = F)
vobj = voom( genes, design, plot=TRUE)
lcpm <- cpm(genes$counts, log = TRUE)
# log counts after DE
boxplot(lcpm, las = 2, main = "")
plot(colSums(t(lcpm)))
Voom weights:
vwts <- voomWithQualityWeights(genes, design=design, normalization="quantile", plot=TRUE)
The random effects of species are taken into account with the duplicateCorrelation function, which estimates the correlation between species. This reflects the between-species variability. The higher the correlation (0-1.0), the higher the variability between species.
corfit <- duplicateCorrelation(vobj,design,block=ExpDesign$species)
corfit$consensus
#[1] 0.751381
Individuals clustered by overall expression

Individuals clustered by Top 100 genes

Individuals clustered by top 50 gene expression

PCA for overall expression

Contrasts
After running the lmFit function, which fits the linear model for each gene in the matrix and takes the random effects correlation into account, the resulting linear model fit is then used to compute the estimated coefficients and standard errors for a given set of contrasts:
fitRan <- lmFit(vobj,design,block=ExpDesign$species,correlation=corfit$consensus)
#colnames(coef(fitRan))
y <- rnorm(n = nrow(design))
dummy.mod <- lm(y ~ physiology*condition*clade,
data = ExpDesign)
pairs <- pairs(emmeans(dummy.mod, ~condition|clade*physiology ), reverse = T)
contrast.matrix <- pairs@linfct
tmp <- pairs@grid
contrasts <- gsub(" ", "", tmp$contrast)
contrasts <- gsub("-", "_v_", contrasts)
contrasts <- paste0(contrasts, "_", tmp$clade, "_", tmp$physiology)
rownames(contrast.matrix) <- contrasts
contrasts
[1] "15_ppt_v_0.2_ppt_Clade1_FW" "15_ppt_v_0.2_ppt_Clade2_FW" "15_ppt_v_0.2_ppt_Clade3_FW"
[4] "15_ppt_v_0.2_ppt_Clade1_M" "15_ppt_v_0.2_ppt_Clade2_M" "15_ppt_v_0.2_ppt_Clade3_M"
tables <- lapply(contrasts, function(contr){
print(contr)
cm <- contrast.matrix[contr,]
ph <- sapply(strsplit(as.character(contr), "_"), tail, 1)
cl <- sapply(strsplit(as.character(contr), "_"), tail, 2)
tmp <- contrasts.fit(fitRan, contrasts = cm)
tmp <- eBayes(tmp)
tmp2 <- topTable(tmp, n = Inf, sort.by = "P")
tmp3 <- tmp2
tmp3$row <- rownames(tmp3)
tmp3 <- merge(ann,tmp3,by.x = "ensembl_peptide_id", by.y = "row", all = TRUE)
tmp3 <- tmp3[order(tmp3$adj.P.Val),]
filename <- paste0(contr, ".csv")
#write.csv(tmp2, file = file.path(dir, filename),quote = F)
tab <- kable(head(tmp2, 20), digits = 5, row.names = F)
header1 <- 6
names(header1) <- paste0("Top 20 genes for ", contr)
header2 <- 6
names(header2) <- paste0("Number of genes with adjusted P < 0.05 = ", length(which(tmp2$adj.P.Val < 0.05)))
header3 <- 6
names(header3) <- paste0("Output file is ", filename)
tab <- tab %>% add_header_above(header3, align = 'l') %>% add_header_above(header2, align = 'l') %>% add_header_above(header1, align = 'l', font_size = "larger", bold = T)
tab <- tab %>% kable_styling()
return(list(tab, nump = length(which(tmp2$adj.P.Val < 0.05))))
}
)
[1] "15_ppt_v_0.2_ppt_Clade1_FW"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade2_FW"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade3_FW"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade1_M"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade2_M"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade3_M"
row names of contrasts don't match col names of coefficients
Three-way contrasts
The number of genes significant for the three-way interaction of condition:physiology:clade:
sigps <- unlist(lapply(tables, function(x)x[[2]]))
sumtab <- data.frame(Comparison = contrasts, `Number of genes with adjusted P < 0.05` = sigps,
check.names = F)
kable(sumtab, align = 'c') %>% kable_styling() %>%
add_header_above(c("Overview of results" = 2), font_size = "larger", bold = T, align = "l")
Two-way contrasts
These genes demonstrate a conserved response to experimental condition across M or FW physiologies, regardless of clade.
y <- rnorm(n = nrow(design))
dummy.mod <- lm(y ~ physiology*condition*clade,
data = ExpDesign)
pairs <- pairs(emmeans(dummy.mod, ~condition|physiology ), reverse = T)
contrast.matrix <- pairs@linfct
tmp <- pairs@grid
contrasts <- gsub(" ", "", tmp$contrast)
contrasts <- gsub("-", "_v_", contrasts)
contrasts <- paste0(contrasts, "_", tmp$physiology)
rownames(contrast.matrix) <- contrasts
contrasts
tables <- lapply(contrasts, function(contr){
#print(contr)
cm <- contrast.matrix[contr,]
ph <- sapply(strsplit(as.character(contr), "_"), tail, 1)
cl <- sapply(strsplit(as.character(contr), "_"), tail, 2)
tmp <- contrasts.fit(fitRan, contrasts = cm)
tmp <- eBayes(tmp)
tmp2 <- topTable(tmp, n = Inf, sort.by = "P")
#tmp3 <- tmp2
#tmp3$row <- rownames(tmp3)
#tmp3 <- merge(ann,tmp3,by.x = "ensembl_peptide_id", by.y = "row", all = TRUE)
#tmp3 <- tmp3[order(tmp3$adj.P.Val),]
filename <- paste0(contr, ".csv")
#write.csv(tmp2, file = file.path(dir, filename),quote = F)
tab <- kable(head(tmp2, 20), digits = 5, row.names = F)
header1 <- 6
names(header1) <- paste0("Top 20 genes for ", contr)
header2 <- 6
names(header2) <- paste0("Number of genes with adjusted P < 0.05 = ", length(which(tmp2$adj.P.Val < 0.05)))
header3 <- 6
names(header3) <- paste0("Output file is ", filename)
tab <- tab %>% add_header_above(header3, align = 'l') %>% add_header_above(header2, align = 'l') %>% add_header_above(header1, align = 'l', font_size = "larger", bold = T)
tab <- tab %>% kable_styling()
return(list(tab, nump = length(which(tmp2$adj.P.Val < 0.05))))
}
)
The number of genes significant for the two-way interaction of condition:physiology, independent of clade:
sigps <- unlist(lapply(tables, function(x)x[[2]]))
sumtab <- data.frame(Comparison = contrasts, `Number of genes with adjusted P < 0.05` = sigps,
check.names = F)
kable(sumtab, align = 'c') %>% kable_styling() %>%
add_header_above(c("Overview of results" = 2), font_size = "larger", bold = T, align = "l")
Condition - main effect
These genes demonstrate a main effect of condition (15 ppt vs. 0.2 ppt), regardless of clade or physiology.
y <- rnorm(n = nrow(design))
dummy.mod <- lm(y ~ physiology*condition*clade,
data = ExpDesign)
pairs <- pairs(emmeans(dummy.mod, ~condition), reverse = T)
contrast.matrix <- pairs@linfct
tmp <- pairs@grid
contrasts <- gsub(" ", "", tmp$contrast)
contrasts <- gsub("-", "_v_", contrasts)
rownames(contrast.matrix) <- contrasts
contrasts
tables <- lapply(contrasts, function(contr){
#print(contr)
cm <- contrast.matrix[contr,]
ph <- sapply(strsplit(as.character(contr), "_"), tail, 1)
cl <- sapply(strsplit(as.character(contr), "_"), tail, 2)
tmp <- contrasts.fit(fitRan, contrasts = cm)
tmp <- eBayes(tmp)
tmp2 <- topTable(tmp, n = Inf, sort.by = "P")
#tmp3 <- tmp2
#tmp3$row <- rownames(tmp3)
#tmp3 <- merge(ann,tmp3,by.x = "ensembl_peptide_id", by.y = "row", all = TRUE)
#tmp3 <- tmp3[order(tmp3$adj.P.Val),]
filename <- paste0(contr, ".csv")
#write.csv(tmp2, file = file.path(dir, filename),quote = F)
tab <- kable(head(tmp2, 20), digits = 5, row.names = F)
header1 <- 6
names(header1) <- paste0("Top 20 genes for ", contr)
header2 <- 6
names(header2) <- paste0("Number of genes with adjusted P < 0.05 = ", length(which(tmp2$adj.P.Val < 0.05)))
header3 <- 6
names(header3) <- paste0("Output file is ", filename)
tab <- tab %>% add_header_above(header3, align = 'l') %>% add_header_above(header2, align = 'l') %>% add_header_above(header1, align = 'l', font_size = "larger", bold = T)
tab <- tab %>% kable_styling()
return(list(tab, nump = length(which(tmp2$adj.P.Val < 0.05))))
}
)
The number of genes significant for the main effect condition:
sigps <- unlist(lapply(tables, function(x)x[[2]]))
sumtab <- data.frame(Comparison = contrasts, `Number of genes with adjusted P < 0.05` = sigps,
check.names = F)
kable(sumtab, align = 'c') %>% kable_styling() %>%
add_header_above(c("Overview of results" = 2), font_size = "larger", bold = T, align = "l")
Heatmaps
Marine-Clade 1 (three-way) response
rld <- log2(mean_norm_counts_ordered_M_Clade1_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_Clade1_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater-Clade 1 (three-way) response
rld <- log2(mean_norm_counts_ordered_FW_Clade1_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_Clade1_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Marine-Clade 2 (three-way) response
rld <- log2(mean_norm_counts_ordered_M_Clade2_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_Clade2_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater-Clade 2 (three-way) response
rld <- log2(mean_norm_counts_ordered_FW_Clade2_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_Clade2_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Marine-Clade 3 (three-way) response
rld <- log2(mean_norm_counts_ordered_M_Clade3_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_Clade3_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater-Clade 3 (three-way) response
rld <- log2(mean_norm_counts_ordered_FW_Clade3_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_Clade3_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Marine physiology (two-way) conserved response
rld <- log2(mean_norm_counts_ordered_M_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater physiology (two-way) conserved response
rld <- log2(mean_norm_counts_ordered_FW_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Condition response (main effect)
rld <- log2(mean_norm_counts_ordered_condition_sig+1)
geneDists <- dist(mean_norm_counts_ordered_condition_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
sessionInfo()
LS0tCnRpdGxlOiAiREVhbmFseXNpc19rZmlzaF9vc21vdGljIgphdXRob3I6ICJMaXNhIEpvaG5zb24iCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvbGxhcHNlZDogbm8KICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQotLS0KCiMgSW50cm9kdWN0aW9uCgpBIG1peGVkIG1vZGVsIHdpdGggcmFuZG9tIGVmZmVjdHMgd2FzIGNob3NlbiBmb3IgdGhpcyBtdWx0aWZhY3RvciBleHBlcmltZW50LCBhbmQgYW5hbHl6ZWQgdXNpbmcgdGhlIGBsaW1tYWAgcGFja2FnZSBpbiBSLiBUaGlzIHBhY2thZ2UgaW1wbGVtZW50cyBhIGxpbmVhciBtb2RlbGluZyBhcHByb2FjaCBhbmQgZW1waXJpY2FsIEJheWVzIHN0YXRpc3RpY3MuIFRoZSBgbGltbWFgIHBhY2thZ2Ugd2l0aCB0aGUgYHZvb21gIG1ldGhvZCBlc3RpbWF0ZXMgdGhlIG1lYW4tdmFyaWFuY2UgcmVsYXRpb25zaGlwIG9mIHRoZSBsb2ctY291bnRzLCBnZW5lcmF0ZXMgYSBwcmVjaXNpb24gd2VpZ2h0IGZvciBlYWNoIG9ic2VydmF0aW9uIGFuZCBlbnRlcnMgdGhlc2UgaW50byB0aGUgbGltbWEgZW1waXJpY2FsIEJheWVzIGFuYWx5c2lzIHBpcGVsaW5lLgoKSW4gdGhpcyBtb2RlbCwgYGNsYWRlYCAobGV2ZWxzID0gQ2xhZGUxLCBDbGFkZTIsIENsYWRlMyksIGBwaHlzaW9sb2d5YCAobGV2ZWxzID0gTWFyaW5lLCBGcmVzaHdhdGVyKSwgYW5kIGV4cGVyaW1lbnRhbCBgY29uZGl0aW9uYCAobGV2ZWxzID0gMTVwcHQsIDAuMnBwdCkgYXJlIGZpeGVkIGVmZmVjdHMgd2hpbGUgYHNwZWNpZXNgIChsZXZlbHMgPSAxNCkgaXMgY29uc2lkZXJlZCBhIHJhbmRvbSBlZmZlY3QuCgpgYGB7ciBMb2FkUGFja2FnZXMsIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBJbnN0YWxsIGZ1bmN0aW9uIGZvciBwYWNrYWdlcyAgICAKcGFja2FnZXM8LWZ1bmN0aW9uKHgpewogIHg8LWFzLmNoYXJhY3RlcihtYXRjaC5jYWxsKClbWzJdXSkKICBpZiAoIXJlcXVpcmUoeCxjaGFyYWN0ZXIub25seT1UUlVFKSl7CiAgICBpbnN0YWxsLnBhY2thZ2VzKHBrZ3M9eCxyZXBvcz0iaHR0cDovL2NyYW4uci1wcm9qZWN0Lm9yZyIpCiAgICByZXF1aXJlKHgsY2hhcmFjdGVyLm9ubHk9VFJVRSkKICB9Cn0KCmJpb2NvbmR1Y3RvcnMgPC0gZnVuY3Rpb24oeCl7CiAgICB4PC0gYXMuY2hhcmFjdGVyKG1hdGNoLmNhbGwoKVtbMl1dKQogICAgaWYgKCFyZXF1aXJlKHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpewogICAgICBzb3VyY2UoImh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9iaW9jTGl0ZS5SIikKICAgICAgYmlvY0xpdGUocGtncz14KQogICAgICByZXF1aXJlKHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKICAgIH0KfQoKcGFja2FnZXMoTUFTUykKcGFja2FnZXMoZ2dwbG90MikKcGFja2FnZXMoZ3Rvb2xzKQpwYWNrYWdlcyhwaGVhdG1hcCkKcGFja2FnZXMoY293cGxvdCkKcGFja2FnZXMoUkNvbG9yQnJld2VyKQpwYWNrYWdlcyhkcGx5cikKcGFja2FnZXModGlkeXIpCnBhY2thZ2VzKGtuaXRyKQpwYWNrYWdlcyhnZ3JlcGVsKQpiaW9jb25kdWN0b3JzKERFU2VxMikKYmlvY29uZHVjdG9ycyhsaW1tYSkKYmlvY29uZHVjdG9ycygnZWRnZVInKQpwYWNrYWdlcyhncGxvdHMpCnBhY2thZ2VzKGxhdHRpY2UpCnBhY2thZ2VzKCJ2c24iKQpiaW9jb25kdWN0b3JzKGJpb21hUnQpCnBhY2thZ2VzKGthYmxlRXh0cmEpCnBhY2thZ2VzKHBoZWF0bWFwKQpwYWNrYWdlcygiU3VtbWFyaXplZEV4cGVyaW1lbnQiKQpwYWNrYWdlcygiZW1tZWFucyIpCnBhY2thZ2VzKGRhdGEudGFibGUpCmBgYAoKVGhlIHJhdyBjb3VudHMgZmlsZSwgZ2VuZXJhdGVkIHdpdGggYE51bVJlYWRzYCBmcm9tIHRoZSBzYWxtb24gKHZlcnNpb24gMC4xMi4wKSBxdWFudGlmaWNhdGlvbiB0b29sIGFuZCBzdW1tYXJpemVkIHdpdGggdGhlIHR4aW1wb3J0IEJpb2NvbmR1Y3RvciBwYWNrYWdlICh2ZXJzaW9uIDEuMTAuMSkgaW4gUiwgY2FuIGJlIGRvd25sb2FkZWQgZnJvbSBhbiBbb3NmIHJlcG9zaXRvcnldKGh0dHBzOi8vb3NmLmlvL200eGVnLykgd2l0aCB0aGlzIFtsaW5rXShodHRwczovL29zZi5pby83dnAzOC9kb3dubG9hZCksIHRoZW4gaW1wb3J0ZWQgaW50byB0aGUgUiBmcmFtZXdvcmsuCgpgYGB7ciBsb2FkZmlsZXMsIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFRoaXMgaXMgdGhlIGNvdW50cyB3aXRoIEV4cGVyaW1lbnRhbCBEZXNpZ24gSW5mbyBpbiB0aGUgbGFzdCA1IHJvd3MKCnNldHdkKCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC9STkFzZXFfMTVraWxsaWZpc2gvREVfc2NyaXB0cy9saW1tYSIpCmlmKCFmaWxlLmV4aXN0cygnfi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvRW5zZW1ibF9zcGVjaWVzX2NvdW50c19kZXNpZ25mYWN0b3JzLmNzdicpKXsKICBkb3dubG9hZC5maWxlKCJodHRwczovL29zZi5pby83dnAzOC9kb3dubG9hZCIsJ0Vuc2VtYmxfc3BlY2llc19jb3VudHNfZGVzaWduZmFjdG9ycy5jc3YnKQp9Cgpjb3VudHNfZGVzaWduIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC9FbnNlbWJsX3NwZWNpZXNfY291bnRzX2Rlc2lnbmZhY3RvcnMuY3N2IixzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgpgYGAKClNhbXBsZXMgZnJvbSBzcGVjaWVzIHdpdGggbG93IG51bWJlcnMgb2YgcmVwbGljYXRlcyB3ZXJlIGRyb3BwZWQgZnJvbSB0aGUgcmF3IGNvdW50cyB0YWJsZSAoKkYuIHplYnJpbnVzKiwgKkYuIG5vdHRpaSosICpGLiBzY2lhZGljdXMqKS4gVGhlIHJhdyBjb3VudHMgdGFibGUgaGFzIHRoZSBmb2xsb3dpbmcgZGltZW5zaW9ucyAoZ2VuZXMgeCBzYW1wbGVzKS4gCgpgYGB7ciBkcm9wc2FtcGxlcyxyZXN1bHRzPSdzaG93Jywgd2FybmluZz1GQUxTRX0KCiNkaW0oY291bnRzX2Rlc2lnbikKI1sxXSAzMDQ3MSAgIDEzMAoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEZvcm1hdCBkZXNpZ24gYW5kIGNvdW50cyBtYXRyaXgKIyBEcm9wIGNvbHVtbnMgd2l0aCBubyBkYXRhCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmRlc2lnbiA8LSBjb3VudHNfZGVzaWduW2NvdW50c19kZXNpZ24kRW5zZW1ibCA9PSAnRW1wdHknLF0KI2Rlc2lnbiR0eXBlIDwtIGMoInNwZWNpZXMiLCJuYXRpdmVfc2FsaW5pdHkiLCJjbGFkZSIsImdyb3VwIiwiY29uZGl0aW9uIikKZHJvcHMgPC0gYygiWCIsIkVuc2VtYmwiLAogICAgICAgICAgICJGX3plYnJpbnVzX0JXXzEucXVhbnQiLCJGX3plYnJpbnVzX0JXXzIucXVhbnQiLAogICAgICAgICAgICJGX3plYnJpbnVzX0ZXXzEucXVhbnQiLCJGX3plYnJpbnVzX0ZXXzIucXVhbnQiLAogICAgICAgICAgICJGX25vdHRpX0ZXXzEucXVhbnQiLCJGX25vdHRpX0ZXXzIucXVhbnQiLAogICAgICAgICAgICJGX3NjaWFkaWN1c19CV18xLnF1YW50IiwiRl9zY2lhZGljdXNfRldfMS5xdWFudCIsIkZfc2NpYWRpY3VzX0ZXXzIucXVhbnQiKQp0cmFuc2Zlcl9kcm9wcyA8LSBjKCJGX3NjaWFkaWN1c190cmFuc2Zlcl8xLnF1YW50IiwiRl9yYXRoYnVuaV90cmFuc2Zlcl8xLnF1YW50IiwiRl9yYXRoYnVuaV90cmFuc2Zlcl8yLnF1YW50IiwiRl9yYXRoYnVuaV90cmFuc2Zlcl8zLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9ncmFuZGlzX3RyYW5zZmVyXzEucXVhbnQiLCJGX2dyYW5kaXNfdHJhbnNmZXJfMi5xdWFudCIsIkZfZ3JhbmRpc190cmFuc2Zlcl8zLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9ub3RhdHVzX3RyYW5zZmVyXzEucXVhbnQiLCJGX25vdGF0dXNfdHJhbnNmZXJfMi5xdWFudCIsIkZfbm90YXR1c190cmFuc2Zlcl8zLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9wYXJ2YXBpbmlzX3RyYW5zZmVyXzEucXVhbnQiLCJGX3BhcnZhcGluaXNfdHJhbnNmZXJfMi5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkxfZ29vZGVpX3RyYW5zZmVyXzEucXVhbnQiLCJMX2dvb2RlaV90cmFuc2Zlcl8yLnF1YW50IiwiTF9nb29kZWlfdHJhbnNmZXJfMy5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkZfb2xpdmFjZW91c190cmFuc2Zlcl8xLnF1YW50IiwiRl9vbGl2YWNlb3VzX3RyYW5zZmVyXzIucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJMX3BhcnZhX3RyYW5zZmVyXzEucXVhbnQiLCJMX3BhcnZhX3RyYW5zZmVyXzIucXVhbnQiLCJMX3BhcnZhX3RyYW5zZmVyXzMucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJGX2hldGVyb2NsaXR1c01EUFBfdHJhbnNmZXJfMS5xdWFudCIsIkZfaGV0ZXJvY2xpdHVzTURQUF90cmFuc2Zlcl8yLnF1YW50IiwiRl9oZXRlcm9jbGl0dXNNRFBQX3RyYW5zZmVyXzMucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJGX3NpbWlsaXNfdHJhbnNmZXJfMS5xdWFudCIsIkZfc2ltaWxpc190cmFuc2Zlcl8yLnF1YW50IiwiRl9zaW1pbGlzX3RyYW5zZmVyXzMucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJGX2RpYXBoYW51c190cmFuc2Zlcl8xLnF1YW50IiwiRl9kaWFwaGFudXNfdHJhbnNmZXJfMi5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkZfY2hyeXNvdHVzX3RyYW5zZmVyXzEucXVhbnQiLCJGX2Nocnlzb3R1c190cmFuc2Zlcl8yLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiQV94ZW5pY2FfdHJhbnNmZXJfMS5xdWFudCIsIkFfeGVuaWNhX3RyYW5zZmVyXzIucXVhbnQiLCJBX3hlbmljYV90cmFuc2Zlcl8zLnF1YW50IiAsCiAgICAgICAgICAgICAgICAgICAgIkZfY2F0YW5hdHVzX3RyYW5zZmVyXzEucXVhbnQiLCJGX2NhdGFuYXR1c190cmFuc2Zlcl8yLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9oZXRlcm9jbGl0dXNNRFBMX3RyYW5zZmVyXzEucXVhbnQiLCJGX2hldGVyb2NsaXR1c01EUExfdHJhbnNmZXJfMi5xdWFudCIsIkZfaGV0ZXJvY2xpdHVzTURQTF90cmFuc2Zlcl8zLnF1YW50IikKY291bnRzPC1jb3VudHNfZGVzaWduWyFjb3VudHNfZGVzaWduJEVuc2VtYmwgPT0gJ0VtcHR5JyxdCnJvd25hbWVzKGNvdW50cyk8LWNvdW50cyRFbnNlbWJsCmRlc2lnbiA8LSBkZXNpZ25bICwgIShuYW1lcyhkZXNpZ24pICVpbiUgZHJvcHMpXQpjb3VudHMgPC0gY291bnRzWyAsICEobmFtZXMoY291bnRzKSAlaW4lIGRyb3BzKV0KZGVzaWduIDwtIGRlc2lnblsgLCAhKG5hbWVzKGRlc2lnbikgJWluJSB0cmFuc2Zlcl9kcm9wcyldCmNvdW50cyA8LSBjb3VudHNbICwgIShuYW1lcyhjb3VudHMpICVpbiUgdHJhbnNmZXJfZHJvcHMpXQojZGltKGRlc2lnbikKI1sxXSAgNSA4MQpkaW0oY291bnRzKQpnZW5lLm5hbWVzPC1yb3duYW1lcyhjb3VudHMpCmRlc2lnbltdIDwtIGxhcHBseSggZGVzaWduLCBmYWN0b3IpCmBgYAoKIyBTYW1wbGUgRGVzaWduIE1hdHJpeAoKQSBtYXRyaXggd2FzIGdlbmVyYXRlZCB1c2luZyB0aGUgZm9sbG93aW5nIG1vZGVsIHdpdGggZml4ZWQgZWZmZWN0czogCgpgYGAKfjAgKyBwaHlzaW9sb2d5KmNvbmRpdGlvbipjbGFkZQpgYGAKVGhlIHJhbmRvbSBlZmZlY3Qgb2YgYHNwZWNpZXNgIHdpbGwgYmUgdGFrZW4gaW50byBhY2NvdW50IGxhdGVyLgoKYGBge3IgZGVzaWduaW5mbyxyZXN1bHRzPSdzaG93Jywgd2FybmluZz1GQUxTRX0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBkZXNpZ24gY2F0ZW9nb3JpZXMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLQoKc3BlY2llczwtYXMuY2hhcmFjdGVyKHVubGlzdChkZXNpZ25bMSxdKSkKcGh5c2lvbG9neTwtYXMuY2hhcmFjdGVyKHVubGlzdChkZXNpZ25bMixdKSkKY2xhZGU8LWFzLmNoYXJhY3Rlcih1bmxpc3QoZGVzaWduWzMsXSkpCmNvbmRpdGlvbjwtYXMuY2hhcmFjdGVyKHVubGlzdChkZXNpZ25bNSxdKSkKY29uZGl0aW9uX3BoeXNpb2xvZ3k8LWFzLnZlY3RvcihwYXN0ZShjb25kaXRpb24scGh5c2lvbG9neSxzZXA9Ii4iKSkKY29uZGl0aW9uX3BoeXNpb2xvZ3lfY2xhZGUgPC0gYXMudmVjdG9yKHBhc3RlKGNvbmRpdGlvbl9waHlzaW9sb2d5LGNsYWRlLHNlcD0iLiIpKQpjb25kaXRpb25fcGh5c2lvbG9neV9jbGFkZSA8LSBhcy52ZWN0b3IocGFzdGUoImdyb3VwIixjb25kaXRpb25fcGh5c2lvbG9neV9jbGFkZSxzZXA9IiIpKQpjb2xzPC1jb2xuYW1lcyhjb3VudHMpCkV4cERlc2lnbiA8LSBkYXRhLmZyYW1lKHJvdy5uYW1lcz1jb2xzLAogICAgICAgICAgICAgICAgICAgICAgICBjb25kaXRpb249Y29uZGl0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICBwaHlzaW9sb2d5ID0gcGh5c2lvbG9neSwKICAgICAgICAgICAgICAgICAgICAgICAgY2xhZGUgPSBjbGFkZSwKICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llcyA9IHNwZWNpZXMsCiAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZT1jb2xzKQpFeHBEZXNpZ24KZGVzaWduID0gbW9kZWwubWF0cml4KCB+MCArIHBoeXNpb2xvZ3kqY29uZGl0aW9uKmNsYWRlLCBFeHBEZXNpZ24pCmNvbG5hbWVzKGRlc2lnbikKIyBjaGVjayByYW5rIG9mIG1hdHJpeAojTWF0cml4OjpyYW5rTWF0cml4KCBkZXNpZ24gKQojZGltKGRlc2lnbikKYGBgCgojIEZpbHRlcmluZyBhbmQgTm9ybWFsaXphdGlvbgoKR2VuZXMgd2l0aCBsb3cgZXhwcmVzc2lvbiBhY3Jvc3Mgc2FtcGxlcyB3ZXJlIGRyb3BwZWQgZnJvbSB0aGUgYW5hbHlzaXMgdXNpbmcgYSBjb25zZXJ2YXRpdmUgYXBwcm9hY2guIFRoZSBmdW5jdGlvbiBgZmlsdGVyQnlFeHByYCB3YXMgdXNlZCBvbiB0aGUgcmF3IGNvdW50cyBtYXRyaXguIEZvciBlYWNoIGBjb25kaXRpb25fcGh5c2lvbG9neWAgZ3JvdXAgKHJlZ2FyZGxlc3Mgb2Ygc3BlY2llcyksIGVhY2ggc2FtcGxlIG11c3QgaGF2ZSBhIG1pbml1bSBjb3VudCBvZiAxMCwgYW5kIGEgZ3JvdXAgbWluaXVtIHRvdGFsIGNvdW50IG9mIDEwMC4gVGhpcyByZWR1Y2VkIHRoZSBjb3VudHMgdGFibGUgdG8gdGhlIGZvbGxvd2luZyBkaW1lbnNpb25zIChnZW5lcyB4IHNhbXBsZXMpOgoKYGBge3IgZmlsdCwgcmVzdWx0cz0ic2hvdyIsd2FybmluZz1GQUxTRX0KCmdlbmUubmFtZXM8LXJvd25hbWVzKGNvdW50cykKY291bnRzPC1hcy5tYXRyaXgoYXMuZGF0YS5mcmFtZShzYXBwbHkoY291bnRzLCBhcy5udW1lcmljKSkpCnJvd25hbWVzKGNvdW50cyk8LWdlbmUubmFtZXMKI2NsYXNzKGNvdW50cykKCmtlZXA8LWZpbHRlckJ5RXhwcihjb3VudHMsZGVzaWduID0gZGVzaWduLGdyb3VwPWNvbmRpdGlvbl9waHlzaW9sb2d5LG1pbi5jb3VudCA9IDEwLCBtaW4udG90YWwuY291bnQgPSAxMDApCmNvdW50cy5maWx0IDwtIGNvdW50c1trZWVwLF0KZGltKGNvdW50cy5maWx0KQojd3JpdGUuY3N2KGNvdW50cy5maWx0LCIuLi8uLi8uLi8yMWtfY291bnRzX2ZpbHRfMzBBcHJpbDIwMTkuY3N2IikKYGBgCgojIEdlbmVzIG9mIEludGVyZXN0CgpBZnRlciBmaWx0cmF0aW9uLCB3ZSBjaGVjayB0aGUgY291bnRzIG1hdHJpeCBmb3IgdGhlIHByZXNlbmNlIG9mIHNldmVyYWwgZ2VuZXMgb2YgaW50ZXJlc3QuIFRoZXNlIGdlbmVzIGhhdmUgZGVtb25zdHJhdGVkIHJlc3BvbnNpdmVuZXNzIHRvIHNhbGluaXR5IGNoYW5nZSBmcm9tIHBhc3Qgc3R1ZGllcy4KCnwgZ2VuZSAgfCBGdW5oZSAgfCBFbnNlbWJsICB8ICAKfC0tLXwtLS18LS0tfC0tLXwtLS18Cnwgenltb2dlbiBncmFudWxlIG1lbWJyYW5lIHByb3RlaW4gMTYgIHwgRnVuaGUyRUttMDI5OTI5ICB8IEVOU0ZIRVAwMDAwMDAwNzIyMC4xICB8ICAKfCB6eW1vZ2VuIGdyYW51bGUgbWVtYnJhbmUgcHJvdGVpbiAxNiAgfCBGdW5oZTJFS20wMjk5MzEgfCBFTlNGSEVQMDAwMDAwMjU4NDEgIHwgCnwgc29sdXRlIGNhcnJpZXIgZmFtaWx5IDEyIG1lbWJlciAzLWxpa2UgKHJlbW92ZWQpICB8IEZ1bmhlMkVLbTAwNjg5NiAgfCAgRU5TRkhFUDAwMDAwMDA5MjE0IHwgCnwgY2hsb3JpZGUgY2hhbm5lbCwgdm9sdGFnZS1zZW5zaXRpdmUgMiAoY2xjbjIpLCB0cmFuc2NyaXB0IHZhcmlhbnQgWDIgKHJlbW92ZWQpICB8IEZ1bmhlMkVLbTAyNDE0OCAgfCAgRU5TRkhFUDAwMDAwMDE5NTEwIHwgCnwgQVRQLXNlbnNpdGl2ZSBpbndhcmQgcmVjdGlmaWVyIHBvdGFzc2l1bSBjaGFubmVsIDEgfCAgRnVuaGUyRUttMDAxOTY1IHwgRU5TRkhFUDAwMDAwMDE1MzgzICB8IAp8IGlud2FyZCByZWN0aWZpZXIgcG90YXNzaXVtIGNoYW5uZWwgMiAgfCAgRnVuaGUyRUttMDIzNzgwIHwgRU5TRkhFUDAwMDAwMDA5NzUzICB8IAp8IGFxdWFwb3Jpbi0zICB8ICAgfCBFTlNGSEVQMDAwMDAwMDY3MjUgIHwgCnwgY2Z0ciAgfCBGdW5oZTJFS20wMjQ1MDEgIHwgRU5TRkhFUDAwMDAwMDA4MzkzICB8IAp8IHBvbHlhbWluZS1tb2R1bGF0ZWQgZmFjdG9yIDEtbGlrZSB8IEZ1bmhlMkVLbTAzMTA0OSAgfCBFTlNGSEVQMDAwMDAwMTMzMjQgIHwgCnwgc29kaXVtL3BvdGFzc2l1bS9jYWxjaXVtIGV4Y2hhbmdlciAyICB8IEZ1bmhlMkVLbTAyNTQ5NyB8IEVOU0ZIRVAwMDAwMDAzNDE3NyB8IAp8IHNlcHRpbi0yQiBpc29mb3JtIFgyICB8ICAgfCBFTlNGSEVQMDAwMDAwMTU3NjUgIHwgCnwgQ0xPQ0staW50ZXJhY3RpbmcgcGFjZW1ha2VyLWxpa2UgIHwgRnVuaGUyRUttMDI2ODQ2ICB8IEVOU0ZIRVAwMDAwMDAxNzMwMyAgfCAKfCB2YXNvcHJlc3NpbiBWMiByZWNlcHRvci1saWtlICB8IEZ1bmhlMkVLbTAyNjcyMSAgfCBFTlNGSEVQMDAwMDAwMDAwMzYgfCAKfCBzb2RpdW0vcG90YXNzaXVtLXRyYW5zcG9ydGluZyBBVFBhc2Ugc3VidW5pdCBiZXRhLTEtaW50ZXJhY3RpbmcgcHJvdGVpbiAxICB8IEZ1bmhlMkVLbTAwMTE3NCAgfCBFTlNGSEVQMDAwMDAwMzExMDggIHwgCnwgc2VwdGluLTIgIHwgRnVuaGUyRUttMDEyMTgyICB8IEVOU0ZIRVAwMDAwMDAxNjg1MyAgfCAKfCBvdG9wZXRyaW4tMiAgfCBGdW5oZTJFS20wMzU0MjcgIHwgRU5TRkhFUDAwMDAwMDI2NDExICB8IAp8IGNsYXVkaW4gOCAgfCBGdW5oZTJFS20wMzc3MTggIHwgRU5TRkhFUDAwMDAwMDA2MjgyICB8IAp8IGNsYXVkaW4gNCAgfCBGdW5oZTJFS20wMDcxNDkgIHwgRU5TRkhFUDAwMDAwMDAzOTA4ICB8IAoKSWYgdGhlIEVuc2VtYmwgSUQgZGlzcGxheXMgYmVsb3csIHRoZSBnZW5lIGlzIHByZXNlbnQgaW4gdGhlIHdob2xlIGRhdGEgc2V0IGFuZCBoYXMgbm90IGJlZW4gZmlsdGVyZWQuCgpgYGB7ciBnb2ksIHJlc3VsdHM9InNob3ciLHdhcm5pbmc9RkFMU0V9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEFuZHJldyBXaGl0ZWhlYWQncyBnZW5lcyBvZiBpbnRlcmVzdDoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgenltb2dlbiBncmFudWxlIG1lbWJyYW5lIHByb3RlaW4gMTYKIyBGdW5oZTJFS20wMjk5MjkKIyBFTlNGSEVQMDAwMDAwMDcyMjAuMQpjb3VudHNmaWx0IDwtIGNvdW50cy5maWx0CmNvdW50c2ZpbHQkcm93IDwtIHJvd25hbWVzKGNvdW50c2ZpbHQpCmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDA3MjIwLjEiXQpnb2kKIyB6eW1vZ2VuIGdyYW51bGUgbWVtYnJhbmUgcHJvdGVpbiAxNgojIEZ1bmhlMkVLbTAyOTkzMQojIEVOU0ZIRVAwMDAwMDAyNTg0MQpnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAyNTg0MSJdCmdvaQojIHNvbHV0ZSBjYXJyaWVyIGZhbWlseSAxMiBtZW1iZXIgMy1saWtlIChyZW1vdmVkKSAKIyBGdW5oZTJFS20wMDY4OTYKIyBFTlNGSEVQMDAwMDAwMDkyMTQKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDkyMTQiXQpnb2kKIyBjaGxvcmlkZSBjaGFubmVsLCB2b2x0YWdlLXNlbnNpdGl2ZSAyIChjbGNuMiksIHRyYW5zY3JpcHQgdmFyaWFudCBYMiAocmVtb3ZlZCkKIyBGdW5oZTJFS20wMjQxNDgKIyBFTlNGSEVQMDAwMDAwMTk1MTAKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMTk1MTAiXQpnb2kKIyBBVFAtc2Vuc2l0aXZlIGlud2FyZCByZWN0aWZpZXIgcG90YXNzaXVtIGNoYW5uZWwgMSAKIyBGdW5oZTJFS20wMDE5NjUKIyBFTlNGSEVQMDAwMDAwMTUzODMKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMTUzODMiXQpnb2kKIyBpbndhcmQgcmVjdGlmaWVyIHBvdGFzc2l1bSBjaGFubmVsIDIKIyBGdW5oZTJFS20wMjM3ODAKIyBFTlNGSEVQMDAwMDAwMDk3NTMKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDk3NTMiXQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIG90aGVyIHNhbGluaXR5IGdlbmVzIG9mIGludGVyZXN0CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIGFxdWFwb3Jpbi0zCiMgRU5TRkhFUDAwMDAwMDA2NzI1CmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDA2NzI1Il0KZ29pCiMgY2Z0cgojIEZ1bmhlMkVLbTAyNDUwMQojIEVOU0ZIRVAwMDAwMDAwODM5Mwpnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAwODM5MyJdCmdvaQojIHBvbHlhbWluZS1tb2R1bGF0ZWQgZmFjdG9yIDEtbGlrZQojIEZ1bmhlMkVLbTAzMTA0OQojIEVOU0ZIRVAwMDAwMDAxMzMyNApnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAxMzMyNCJdCmdvaQojIHNvZGl1bS9wb3Rhc3NpdW0vY2FsY2l1bSBleGNoYW5nZXIgMgojIEVOU0ZIRVAwMDAwMDAzNDE3NwojIEZ1bmhlMkVLbTAyNTQ5Nwpnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAzNDE3NyJdCmdvaQojIHNlcHRpbi0yQiBpc29mb3JtIFgyCiMgRU5TRkhFUDAwMDAwMDE1NzY1CmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDE1NzY1Il0KZ29pCiMgQ0xPQ0staW50ZXJhY3RpbmcgcGFjZW1ha2VyLWxpa2UKIyBFTlNGSEVQMDAwMDAwMTczMDMKIyBGdW5oZTJFS20wMjY4NDYKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMTczMDMiXQpnb2kKIyB2YXNvcHJlc3NpbiBWMiByZWNlcHRvci1saWtlCiMgRnVuaGUyRUttMDI2NzIxCiMgRU5TRkhFUDAwMDAwMDAwMDM2CmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDAwMDM2Il0KZ29pCiMgc29kaXVtL3BvdGFzc2l1bS10cmFuc3BvcnRpbmcgQVRQYXNlIHN1YnVuaXQgYmV0YS0xLWludGVyYWN0aW5nIHByb3RlaW4gMQojIEVOU0ZIRVAwMDAwMDAzMTEwOAojIEZ1bmhlMkVLbTAwMTE3NApnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAzMTEwOCJdCmdvaQojIHNlcHRpbi0yCiMgRnVuaGUyRUttMDEyMTgyCiMgRU5TRkhFUDAwMDAwMDE2ODUzCmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDE2ODUzIl0KZ29pCiMgb3RvcGV0cmluLTIKIyBGdW5oZTJFS20wMzU0MjcKIyBFTlNGSEVQMDAwMDAwMjY0MTEKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMjY0MTEiXQpnb2kKIyBjbGF1ZGluIDgKIyBGdW5oZTJFS20wMzc3MTgKIyBFTlNGSEVQMDAwMDAwMDYyODIKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDYyODIiXQpnb2kKIyBjbGF1ZGluIDQKIyBFTlNGSEVQMDAwMDAwMDM5MDgKIyBGdW5oZTJFS20wMDcxNDkKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDM5MDgiXQpnb2kKYWxsX2dvaTwtYygiRU5TRkhFUDAwMDAwMDA3MjIwLjEiLCJFTlNGSEVQMDAwMDAwMjU4NDEiLCJFTlNGSEVQMDAwMDAwMTk1MTAiLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTUzODMiLCJFTlNGSEVQMDAwMDAwMDk3NTMiLCJFTlNGSEVQMDAwMDAwMDY3MjUiLCJFTlNGSEVQMDAwMDAwMDgzOTMiLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTMzMjQiLCJFTlNGSEVQMDAwMDAwMDE2MDkiLCJFTlNGSEVQMDAwMDAwMTMzMjQiLCJFTlNGSEVQMDAwMDAwMzQxNzciLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTU3NjUiLCJFTlNGSEVQMDAwMDAwMTczMDMiLCJFTlNGSEVQMDAwMDAwMDAwMzYiLCJFTlNGSEVQMDAwMDAwMzExMDgiLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTY4NTMiLCJFTlNGSEVQMDAwMDAwMDM5MDgiKQpgYGAKCiMgRXhwbG9yYXRvcnkgUGxvdHMKCkxvZyBjb3VudHMgYmVmb3JlIG5vcm1hbGl6YXRpb246CmBgYHtyIHJhdywgcmVzdWx0cz0ic2hvdyIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSwgd2FybmluZz1GQUxTRX0KCiMgbG9nIGNvdW50cyBiZWZvcmUgREUKYm94cGxvdChsb2coY291bnRzLmZpbHQrMSksIGxhcyA9IDIsIG1haW4gPSAiIikKCmBgYAoKTG9nIGNvdW50cyBhZnRlciBjcG0gbm9ybWFsaXphdGlvbgpgYGB7ciBub3JtLCByZXN1bHRzPSJzaG93IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpLCB3YXJuaW5nPUZBTFNFfQojIC0tLS0tLS0tLS0tLS0tLQoKIyBERSBhbmFseXNpcwoKIyAtLS0tLS0tLS0tLS0tLS0KCmdlbmVzID0gREdFTGlzdChjb3VudCA9IGNvdW50cy5maWx0LCBncm91cCA9IGNvbmRpdGlvbl9waHlzaW9sb2d5X2NsYWRlKQpnZW5lcyA9IGNhbGNOb3JtRmFjdG9ycyggZ2VuZXMgKQoKIyB3cml0ZSBub3JtYWxpemVkIGNvdW50cwpkaXIgPC0gIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLyIKdG1wIDwtIGFzLmRhdGEuZnJhbWUoY3BtKGdlbmVzKSkKdG1wJEVuc2VtYmwgPC0gcm93bmFtZXModG1wKQp0bXAgPC0gZHBseXI6OnNlbGVjdCh0bXAsIEVuc2VtYmwsIGV2ZXJ5dGhpbmcoKSkKd3JpdGUuY3N2KHRtcCwgZmlsZSA9IGZpbGUucGF0aChkaXIsICJub3JtYWxpemVkX2NvdW50cy5jc3YiKSwgcXVvdGUgPSBGLCByb3cubmFtZXMgPSBGKQoKdm9iaiA9IHZvb20oIGdlbmVzLCBkZXNpZ24sIHBsb3Q9VFJVRSkKbGNwbSA8LSBjcG0oZ2VuZXMkY291bnRzLCBsb2cgPSBUUlVFKQoKIyBsb2cgY291bnRzIGFmdGVyIERFCgpib3hwbG90KGxjcG0sIGxhcyA9IDIsIG1haW4gPSAiIikKcGxvdChjb2xTdW1zKHQobGNwbSkpKQpgYGAKClZvb20gd2VpZ2h0czoKCmBgYHtyIHZvb20sIHJlc3VsdHM9InNob3ciLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyksd2FybmluZz1GQUxTRSB9Cgp2d3RzIDwtIHZvb21XaXRoUXVhbGl0eVdlaWdodHMoZ2VuZXMsIGRlc2lnbj1kZXNpZ24sIG5vcm1hbGl6YXRpb249InF1YW50aWxlIiwgcGxvdD1UUlVFKQpgYGAKClRoZSByYW5kb20gZWZmZWN0cyBvZiBgc3BlY2llc2AgYXJlIHRha2VuIGludG8gYWNjb3VudCB3aXRoIHRoZSBgZHVwbGljYXRlQ29ycmVsYXRpb25gIGZ1bmN0aW9uLCB3aGljaCBlc3RpbWF0ZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gc3BlY2llcy4gVGhpcyByZWZsZWN0cyB0aGUgYmV0d2Vlbi1zcGVjaWVzIHZhcmlhYmlsaXR5LiBUaGUgaGlnaGVyIHRoZSBjb3JyZWxhdGlvbiAoMC0xLjApLCB0aGUgaGlnaGVyIHRoZSB2YXJpYWJpbGl0eSBiZXR3ZWVuIHNwZWNpZXMuCgpgYGB7ciByYW5kb21lZmZlY3RzLCByZXN1bHRzPSJzaG93IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpLHdhcm5pbmc9RkFMU0UgfQpjb3JmaXQgPC0gZHVwbGljYXRlQ29ycmVsYXRpb24odm9iaixkZXNpZ24sYmxvY2s9RXhwRGVzaWduJHNwZWNpZXMpCgpjb3JmaXQkY29uc2Vuc3VzCiNbMV0gMC43NTEzODEKYGBgCgojIyMgSW5kaXZpZHVhbHMgY2x1c3RlcmVkIGJ5IG92ZXJhbGwgZXhwcmVzc2lvbgoKYGBge3IgUGxhaW5IZWF0bWFwLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpjb3VudHNfcm91bmQ8LXJvdW5kKGNvdW50cy5maWx0LGRpZ2l0cz0wKQpkZHMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBjb3VudHNfcm91bmQsY29sRGF0YSA9IEV4cERlc2lnbixkZXNpZ24gPSBkZXNpZ24pCnJsZCA8LSB2c3QoZGRzLCBibGluZCA9IEZBTFNFLGZpdFR5cGU9J2xvY2FsJykKc2FtcGxlRGlzdHMgPC0gZGlzdCh0KGFzc2F5KHJsZCkpKQpkZiA8LSBhcy5kYXRhLmZyYW1lKGNvbERhdGEoZGRzKVssYygicGh5c2lvbG9neSIsImNvbmRpdGlvbiIsImNsYWRlIildKQpzYW1wbGVEaXN0TWF0cml4IDwtIGFzLm1hdHJpeCggc2FtcGxlRGlzdHMgKQpjb2xvcnMgPC0gY29sb3JSYW1wUGFsZXR0ZSggcmV2KGJyZXdlci5wYWwoOSwgIkJsdWVzIikpICkoMjU1KQpwaGVhdG1hcChzYW1wbGVEaXN0TWF0cml4LAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBzYW1wbGVEaXN0cywKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gc2FtcGxlRGlzdHMsCiAgICAgICAgIGNvbCA9IGNvbG9ycywgYW5ub3RhdGlvbiA9IGRmLCBzaG93X3Jvd25hbWVzPUYpCmBgYAoKIyMjIEluZGl2aWR1YWxzIGNsdXN0ZXJlZCBieSBUb3AgMTAwIGdlbmVzCgpgYGB7ciBNaW5pUGxhaW5HZW5lSGVhdG1hcCwgZWNobz1GQUxTRSwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyksd2FybmluZz1GQUxTRX0Kc2VsZWN0MTAwIDwtIG9yZGVyKHJvd01lYW5zKGNvdW50cyhkZHMsbm9ybWFsaXplZD1GQUxTRSkpLGRlY3JlYXNpbmc9VFJVRSlbMToxMDBdCnNhbXBsZURpc3RzIDwtIGRpc3QodChhc3NheShybGQpW3NlbGVjdDEwMCxdKSkKcGhlYXRtYXAoYXNzYXkocmxkKVtzZWxlY3QxMDAsXSwgc2hvd19yb3duYW1lcz1UUlVFLGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IHNhbXBsZURpc3RzLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBzYW1wbGVEaXN0cywgYW5ub3RhdGlvbl9jb2w9ZGYpCmBgYAoKIyMjIEluZGl2aWR1YWxzIGNsdXN0ZXJlZCBieSB0b3AgNTAgZ2VuZSBleHByZXNzaW9uCgoKYGBge3IgTWluaVBsYWluSGVhdG1hcCwgZWNobz1GQUxTRSwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyksd2FybmluZz1GQUxTRX0KCnNlbGVjdDUwIDwtIG9yZGVyKHJvd01lYW5zKGNvdW50cyhkZHMsbm9ybWFsaXplZD1GQUxTRSkpLGRlY3JlYXNpbmc9VFJVRSlbMTo1MF0KCnNhbXBsZURpc3RzIDwtIGRpc3QodChhc3NheShybGQpW3NlbGVjdDUwLF0pKQpzYW1wbGVEaXN0TWF0cml4IDwtIGFzLm1hdHJpeCggc2FtcGxlRGlzdHMgKQoKcGhlYXRtYXAoc2FtcGxlRGlzdE1hdHJpeCwgc2hvd19yb3duYW1lcz1ULGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IHNhbXBsZURpc3RzLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBzYW1wbGVEaXN0cywgYW5ub3RhdGlvbl9jb2w9ZGYpCmBgYAoKIyMjIFBDQSBmb3Igb3ZlcmFsbCBleHByZXNzaW9uCgpgYGB7ciBwbGFpblBDQSwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyksd2FybmluZz1GQUxTRX0KCmNvd3Bsb3Q6OnBsb3RfZ3JpZCggcGxvdFBDQShybGQsIGludGdyb3VwPSJjb25kaXRpb24iKSwKICAgICAgICAgICAgICAgICAgICBwbG90UENBKHJsZCwgaW50Z3JvdXA9InBoeXNpb2xvZ3kiKSwKICAgICAgICAgICAgICAgICAgICBwbG90UENBKHJsZCwgaW50Z3JvdXA9ImNsYWRlIiksCiAgICAgICAgICAgICAgICAgICAgcGxvdFBDQShybGQsIGludGdyb3VwPWMoImNsYWRlIiwicGh5c2lvbG9neSIsImNvbmRpdGlvbiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ249ImMiLCBuY29sPTIpCmBgYAoKIyBDb250cmFzdHMKCkFmdGVyIHJ1bm5pbmcgdGhlIGBsbUZpdGAgZnVuY3Rpb24sIHdoaWNoIGZpdHMgdGhlIGxpbmVhciBtb2RlbCBmb3IgZWFjaCBnZW5lIGluIHRoZSBtYXRyaXggYW5kIHRha2VzIHRoZSByYW5kb20gZWZmZWN0cyBjb3JyZWxhdGlvbiBpbnRvIGFjY291bnQsIHRoZSByZXN1bHRpbmcgbGluZWFyIG1vZGVsIGZpdCBpcyB0aGVuIHVzZWQgdG8gY29tcHV0ZSB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cyBhbmQgc3RhbmRhcmQgZXJyb3JzIGZvciBhIGdpdmVuIHNldCBvZiBjb250cmFzdHM6CgpgYGB7ciBsbWZpdCwgcmVzdWx0cz0ic2hvdyIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFIH0KZml0UmFuIDwtIGxtRml0KHZvYmosZGVzaWduLGJsb2NrPUV4cERlc2lnbiRzcGVjaWVzLGNvcnJlbGF0aW9uPWNvcmZpdCRjb25zZW5zdXMpCiNjb2xuYW1lcyhjb2VmKGZpdFJhbikpCnkgPC0gcm5vcm0obiA9IG5yb3coZGVzaWduKSkKZHVtbXkubW9kIDwtIGxtKHkgfiBwaHlzaW9sb2d5KmNvbmRpdGlvbipjbGFkZSwgCiAgICAgICAgICAgICAgICBkYXRhID0gRXhwRGVzaWduKQpwYWlycyA8LSBwYWlycyhlbW1lYW5zKGR1bW15Lm1vZCwgfmNvbmRpdGlvbnxjbGFkZSpwaHlzaW9sb2d5ICksIHJldmVyc2UgPSBUKQpjb250cmFzdC5tYXRyaXggPC0gcGFpcnNAbGluZmN0CnRtcCA8LSBwYWlyc0BncmlkCmNvbnRyYXN0cyA8LSBnc3ViKCIgIiwgIiIsIHRtcCRjb250cmFzdCkKY29udHJhc3RzIDwtIGdzdWIoIi0iLCAiX3ZfIiwgY29udHJhc3RzKQpjb250cmFzdHMgPC0gcGFzdGUwKGNvbnRyYXN0cywgIl8iLCB0bXAkY2xhZGUsICJfIiwgdG1wJHBoeXNpb2xvZ3kpCnJvd25hbWVzKGNvbnRyYXN0Lm1hdHJpeCkgPC0gY29udHJhc3RzCgpjb250cmFzdHMKYGBgCgoKYGBge3IgY29udHJhc3RzMSwgcmVzdWx0cz0ic2hvdyIsd2FybmluZz1GQUxTRX0KdGFibGVzIDwtIGxhcHBseShjb250cmFzdHMsIGZ1bmN0aW9uKGNvbnRyKXsKICAgICNwcmludChjb250cikKICAgIGNtIDwtIGNvbnRyYXN0Lm1hdHJpeFtjb250cixdCiAgICBwaCA8LSBzYXBwbHkoc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKGNvbnRyKSwgIl8iKSwgdGFpbCwgMSkKICAgIGNsIDwtIHNhcHBseShzdHJzcGxpdChhcy5jaGFyYWN0ZXIoY29udHIpLCAiXyIpLCB0YWlsLCAyKQogICAgdG1wIDwtIGNvbnRyYXN0cy5maXQoZml0UmFuLCBjb250cmFzdHMgPSBjbSkKICAgIHRtcCA8LSBlQmF5ZXModG1wKQogICAgdG1wMiA8LSB0b3BUYWJsZSh0bXAsIG4gPSBJbmYsIHNvcnQuYnkgPSAiUCIpCiAgICAjdG1wMyA8LSB0bXAyCiAgICAjdG1wMyRyb3cgPC0gcm93bmFtZXModG1wMykKICAgICN0bXAzIDwtIG1lcmdlKGFubix0bXAzLGJ5LnggPSAiZW5zZW1ibF9wZXB0aWRlX2lkIiwgYnkueSA9ICJyb3ciLCBhbGwgPSBUUlVFKQogICAgI3RtcDMgPC0gdG1wM1tvcmRlcih0bXAzJGFkai5QLlZhbCksXQogICAgZmlsZW5hbWUgPC0gcGFzdGUwKGNvbnRyLCAiLmNzdiIpCiAgICAjd3JpdGUuY3N2KHRtcDIsIGZpbGUgPSBmaWxlLnBhdGgoZGlyLCBmaWxlbmFtZSkscXVvdGUgPSBGKQogICAgdGFiIDwtIGthYmxlKGhlYWQodG1wMiwgMjApLCBkaWdpdHMgPSA1LCByb3cubmFtZXMgPSBGKQogICAgaGVhZGVyMSA8LSA2CiAgICBuYW1lcyhoZWFkZXIxKSA8LSBwYXN0ZTAoIlRvcCAyMCBnZW5lcyBmb3IgIiwgY29udHIpCiAgICBoZWFkZXIyIDwtIDYKICAgIG5hbWVzKGhlYWRlcjIpIDwtIHBhc3RlMCgiTnVtYmVyIG9mIGdlbmVzIHdpdGggYWRqdXN0ZWQgUCA8IDAuMDUgPSAiLCBsZW5ndGgod2hpY2godG1wMiRhZGouUC5WYWwgPCAwLjA1KSkpCiAgICBoZWFkZXIzIDwtIDYKICAgIG5hbWVzKGhlYWRlcjMpIDwtIHBhc3RlMCgiT3V0cHV0IGZpbGUgaXMgIiwgZmlsZW5hbWUpCiAgICB0YWIgPC0gdGFiICU+JSBhZGRfaGVhZGVyX2Fib3ZlKGhlYWRlcjMsIGFsaWduID0gJ2wnKSAlPiUgYWRkX2hlYWRlcl9hYm92ZShoZWFkZXIyLCBhbGlnbiA9ICdsJykgJT4lIGFkZF9oZWFkZXJfYWJvdmUoaGVhZGVyMSwgYWxpZ24gPSAnbCcsIGZvbnRfc2l6ZSA9ICJsYXJnZXIiLCBib2xkID0gVCkKICAgIHRhYiA8LSB0YWIgJT4lIGthYmxlX3N0eWxpbmcoKQogICAgcmV0dXJuKGxpc3QodGFiLCBudW1wID0gbGVuZ3RoKHdoaWNoKHRtcDIkYWRqLlAuVmFsIDwgMC4wNSkpKSkKfQopCgpgYGAKCiMgVGhyZWUtd2F5IGNvbnRyYXN0cwoKVGhlIG51bWJlciBvZiBnZW5lcyBzaWduaWZpY2FudCBmb3IgdGhlIHRocmVlLXdheSBpbnRlcmFjdGlvbiBvZiBgY29uZGl0aW9uOnBoeXNpb2xvZ3k6Y2xhZGVgOiAKCmBgYHtyIHRocmVld2F5LCByZXN1bHRzPSJzaG93Iix3YXJuaW5nPUZBTFNFfQpzaWdwcyA8LSB1bmxpc3QobGFwcGx5KHRhYmxlcywgZnVuY3Rpb24oeCl4W1syXV0pKQpzdW10YWIgPC0gZGF0YS5mcmFtZShDb21wYXJpc29uID0gY29udHJhc3RzLCBgTnVtYmVyIG9mIGdlbmVzIHdpdGggYWRqdXN0ZWQgUCA8IDAuMDVgID0gc2lncHMsCiAgICAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRikKa2FibGUoc3VtdGFiLCBhbGlnbiA9ICdjJykgJT4lIGthYmxlX3N0eWxpbmcoKSAlPiUKICBhZGRfaGVhZGVyX2Fib3ZlKGMoIk92ZXJ2aWV3IG9mIHJlc3VsdHMiID0gMiksIGZvbnRfc2l6ZSA9ICJsYXJnZXIiLCBib2xkID0gVCwgYWxpZ24gPSAibCIpCmBgYAoKIyBUd28td2F5IGNvbnRyYXN0cwoKVGhlc2UgZ2VuZXMgZGVtb25zdHJhdGUgYSBjb25zZXJ2ZWQgcmVzcG9uc2UgdG8gZXhwZXJpbWVudGFsIGNvbmRpdGlvbiBhY3Jvc3MgTSBvciBGVyBwaHlzaW9sb2dpZXMsIHJlZ2FyZGxlc3Mgb2YgY2xhZGUuIAoKYGBge3IgdHdvd2F5LCByZXN1bHRzPSJzaG93Iix3YXJuaW5nPUZBTFNFfQp5IDwtIHJub3JtKG4gPSBucm93KGRlc2lnbikpCmR1bW15Lm1vZCA8LSBsbSh5IH4gcGh5c2lvbG9neSpjb25kaXRpb24qY2xhZGUsIAogICAgICAgICAgICAgICAgZGF0YSA9IEV4cERlc2lnbikKcGFpcnMgPC0gcGFpcnMoZW1tZWFucyhkdW1teS5tb2QsIH5jb25kaXRpb258cGh5c2lvbG9neSApLCByZXZlcnNlID0gVCkKY29udHJhc3QubWF0cml4IDwtIHBhaXJzQGxpbmZjdAp0bXAgPC0gcGFpcnNAZ3JpZApjb250cmFzdHMgPC0gZ3N1YigiICIsICIiLCB0bXAkY29udHJhc3QpCmNvbnRyYXN0cyA8LSBnc3ViKCItIiwgIl92XyIsIGNvbnRyYXN0cykKY29udHJhc3RzIDwtIHBhc3RlMChjb250cmFzdHMsICJfIiwgdG1wJHBoeXNpb2xvZ3kpCnJvd25hbWVzKGNvbnRyYXN0Lm1hdHJpeCkgPC0gY29udHJhc3RzCgpjb250cmFzdHMKCnRhYmxlcyA8LSBsYXBwbHkoY29udHJhc3RzLCBmdW5jdGlvbihjb250cil7CiAgI3ByaW50KGNvbnRyKQogIGNtIDwtIGNvbnRyYXN0Lm1hdHJpeFtjb250cixdCiAgcGggPC0gc2FwcGx5KHN0cnNwbGl0KGFzLmNoYXJhY3Rlcihjb250ciksICJfIiksIHRhaWwsIDEpCiAgY2wgPC0gc2FwcGx5KHN0cnNwbGl0KGFzLmNoYXJhY3Rlcihjb250ciksICJfIiksIHRhaWwsIDIpCiAgdG1wIDwtIGNvbnRyYXN0cy5maXQoZml0UmFuLCBjb250cmFzdHMgPSBjbSkKICB0bXAgPC0gZUJheWVzKHRtcCkKICB0bXAyIDwtIHRvcFRhYmxlKHRtcCwgbiA9IEluZiwgc29ydC5ieSA9ICJQIikKICAjdG1wMyA8LSB0bXAyCiAgI3RtcDMkcm93IDwtIHJvd25hbWVzKHRtcDMpCiAgI3RtcDMgPC0gbWVyZ2UoYW5uLHRtcDMsYnkueCA9ICJlbnNlbWJsX3BlcHRpZGVfaWQiLCBieS55ID0gInJvdyIsIGFsbCA9IFRSVUUpCiAgI3RtcDMgPC0gdG1wM1tvcmRlcih0bXAzJGFkai5QLlZhbCksXQogIGZpbGVuYW1lIDwtIHBhc3RlMChjb250ciwgIi5jc3YiKQogICN3cml0ZS5jc3YodG1wMiwgZmlsZSA9IGZpbGUucGF0aChkaXIsIGZpbGVuYW1lKSxxdW90ZSA9IEYpCiAgdGFiIDwtIGthYmxlKGhlYWQodG1wMiwgMjApLCBkaWdpdHMgPSA1LCByb3cubmFtZXMgPSBGKQogIGhlYWRlcjEgPC0gNgogIG5hbWVzKGhlYWRlcjEpIDwtIHBhc3RlMCgiVG9wIDIwIGdlbmVzIGZvciAiLCBjb250cikKICBoZWFkZXIyIDwtIDYKICBuYW1lcyhoZWFkZXIyKSA8LSBwYXN0ZTAoIk51bWJlciBvZiBnZW5lcyB3aXRoIGFkanVzdGVkIFAgPCAwLjA1ID0gIiwgbGVuZ3RoKHdoaWNoKHRtcDIkYWRqLlAuVmFsIDwgMC4wNSkpKQogIGhlYWRlcjMgPC0gNgogIG5hbWVzKGhlYWRlcjMpIDwtIHBhc3RlMCgiT3V0cHV0IGZpbGUgaXMgIiwgZmlsZW5hbWUpCiAgdGFiIDwtIHRhYiAlPiUgYWRkX2hlYWRlcl9hYm92ZShoZWFkZXIzLCBhbGlnbiA9ICdsJykgJT4lIGFkZF9oZWFkZXJfYWJvdmUoaGVhZGVyMiwgYWxpZ24gPSAnbCcpICU+JSBhZGRfaGVhZGVyX2Fib3ZlKGhlYWRlcjEsIGFsaWduID0gJ2wnLCBmb250X3NpemUgPSAibGFyZ2VyIiwgYm9sZCA9IFQpCiAgdGFiIDwtIHRhYiAlPiUga2FibGVfc3R5bGluZygpCiAgcmV0dXJuKGxpc3QodGFiLCBudW1wID0gbGVuZ3RoKHdoaWNoKHRtcDIkYWRqLlAuVmFsIDwgMC4wNSkpKSkKfQoKKQpgYGAKClRoZSBudW1iZXIgb2YgZ2VuZXMgc2lnbmlmaWNhbnQgZm9yIHRoZSB0d28td2F5IGludGVyYWN0aW9uIG9mIGBjb25kaXRpb246cGh5c2lvbG9neWAsIGluZGVwZW5kZW50IG9mIGNsYWRlOiAKCmBgYHtyIHR3b3dheXJlc3VsdHMsIHJlc3VsdHM9InNob3ciLHdhcm5pbmc9RkFMU0V9CnNpZ3BzIDwtIHVubGlzdChsYXBwbHkodGFibGVzLCBmdW5jdGlvbih4KXhbWzJdXSkpCnN1bXRhYiA8LSBkYXRhLmZyYW1lKENvbXBhcmlzb24gPSBjb250cmFzdHMsIGBOdW1iZXIgb2YgZ2VuZXMgd2l0aCBhZGp1c3RlZCBQIDwgMC4wNWAgPSBzaWdwcywKICAgICAgICAgICAgICAgICAgICAgY2hlY2submFtZXMgPSBGKQprYWJsZShzdW10YWIsIGFsaWduID0gJ2MnKSAlPiUga2FibGVfc3R5bGluZygpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiT3ZlcnZpZXcgb2YgcmVzdWx0cyIgPSAyKSwgZm9udF9zaXplID0gImxhcmdlciIsIGJvbGQgPSBULCBhbGlnbiA9ICJsIikKYGBgCgojIENvbmRpdGlvbiAtIG1haW4gZWZmZWN0CgpUaGVzZSBnZW5lcyBkZW1vbnN0cmF0ZSBhIG1haW4gZWZmZWN0IG9mIGNvbmRpdGlvbiAoMTUgcHB0IHZzLiAwLjIgcHB0KSwgcmVnYXJkbGVzcyBvZiBjbGFkZSBvciBwaHlzaW9sb2d5LgoKYGBge3IgY29uZGl0aW9ubWFpbiwgcmVzdWx0cz0ic2hvdyIsd2FybmluZz1GQUxTRX0KeSA8LSBybm9ybShuID0gbnJvdyhkZXNpZ24pKQpkdW1teS5tb2QgPC0gbG0oeSB+IHBoeXNpb2xvZ3kqY29uZGl0aW9uKmNsYWRlLCAKICAgICAgICAgICAgICAgIGRhdGEgPSBFeHBEZXNpZ24pCnBhaXJzIDwtIHBhaXJzKGVtbWVhbnMoZHVtbXkubW9kLCB+Y29uZGl0aW9uKSwgcmV2ZXJzZSA9IFQpCmNvbnRyYXN0Lm1hdHJpeCA8LSBwYWlyc0BsaW5mY3QKdG1wIDwtIHBhaXJzQGdyaWQKY29udHJhc3RzIDwtIGdzdWIoIiAiLCAiIiwgdG1wJGNvbnRyYXN0KQpjb250cmFzdHMgPC0gZ3N1YigiLSIsICJfdl8iLCBjb250cmFzdHMpCnJvd25hbWVzKGNvbnRyYXN0Lm1hdHJpeCkgPC0gY29udHJhc3RzCgpjb250cmFzdHMKCnRhYmxlcyA8LSBsYXBwbHkoY29udHJhc3RzLCBmdW5jdGlvbihjb250cil7CiAgI3ByaW50KGNvbnRyKQogIGNtIDwtIGNvbnRyYXN0Lm1hdHJpeFtjb250cixdCiAgcGggPC0gc2FwcGx5KHN0cnNwbGl0KGFzLmNoYXJhY3Rlcihjb250ciksICJfIiksIHRhaWwsIDEpCiAgY2wgPC0gc2FwcGx5KHN0cnNwbGl0KGFzLmNoYXJhY3Rlcihjb250ciksICJfIiksIHRhaWwsIDIpCiAgdG1wIDwtIGNvbnRyYXN0cy5maXQoZml0UmFuLCBjb250cmFzdHMgPSBjbSkKICB0bXAgPC0gZUJheWVzKHRtcCkKICB0bXAyIDwtIHRvcFRhYmxlKHRtcCwgbiA9IEluZiwgc29ydC5ieSA9ICJQIikKICAjdG1wMyA8LSB0bXAyCiAgI3RtcDMkcm93IDwtIHJvd25hbWVzKHRtcDMpCiAgI3RtcDMgPC0gbWVyZ2UoYW5uLHRtcDMsYnkueCA9ICJlbnNlbWJsX3BlcHRpZGVfaWQiLCBieS55ID0gInJvdyIsIGFsbCA9IFRSVUUpCiAgI3RtcDMgPC0gdG1wM1tvcmRlcih0bXAzJGFkai5QLlZhbCksXQogIGZpbGVuYW1lIDwtIHBhc3RlMChjb250ciwgIi5jc3YiKQogICN3cml0ZS5jc3YodG1wMiwgZmlsZSA9IGZpbGUucGF0aChkaXIsIGZpbGVuYW1lKSxxdW90ZSA9IEYpCiAgdGFiIDwtIGthYmxlKGhlYWQodG1wMiwgMjApLCBkaWdpdHMgPSA1LCByb3cubmFtZXMgPSBGKQogIGhlYWRlcjEgPC0gNgogIG5hbWVzKGhlYWRlcjEpIDwtIHBhc3RlMCgiVG9wIDIwIGdlbmVzIGZvciAiLCBjb250cikKICBoZWFkZXIyIDwtIDYKICBuYW1lcyhoZWFkZXIyKSA8LSBwYXN0ZTAoIk51bWJlciBvZiBnZW5lcyB3aXRoIGFkanVzdGVkIFAgPCAwLjA1ID0gIiwgbGVuZ3RoKHdoaWNoKHRtcDIkYWRqLlAuVmFsIDwgMC4wNSkpKQogIGhlYWRlcjMgPC0gNgogIG5hbWVzKGhlYWRlcjMpIDwtIHBhc3RlMCgiT3V0cHV0IGZpbGUgaXMgIiwgZmlsZW5hbWUpCiAgdGFiIDwtIHRhYiAlPiUgYWRkX2hlYWRlcl9hYm92ZShoZWFkZXIzLCBhbGlnbiA9ICdsJykgJT4lIGFkZF9oZWFkZXJfYWJvdmUoaGVhZGVyMiwgYWxpZ24gPSAnbCcpICU+JSBhZGRfaGVhZGVyX2Fib3ZlKGhlYWRlcjEsIGFsaWduID0gJ2wnLCBmb250X3NpemUgPSAibGFyZ2VyIiwgYm9sZCA9IFQpCiAgdGFiIDwtIHRhYiAlPiUga2FibGVfc3R5bGluZygpCiAgcmV0dXJuKGxpc3QodGFiLCBudW1wID0gbGVuZ3RoKHdoaWNoKHRtcDIkYWRqLlAuVmFsIDwgMC4wNSkpKSkKfQoKKQpgYGAKClRoZSBudW1iZXIgb2YgZ2VuZXMgc2lnbmlmaWNhbnQgZm9yIHRoZSBtYWluIGVmZmVjdCBgY29uZGl0aW9uYDogCgpgYGB7ciBjb25kaXRpb25yZXN1bHRzLCByZXN1bHRzPSJzaG93Iix3YXJuaW5nPUZBTFNFfQpzaWdwcyA8LSB1bmxpc3QobGFwcGx5KHRhYmxlcywgZnVuY3Rpb24oeCl4W1syXV0pKQpzdW10YWIgPC0gZGF0YS5mcmFtZShDb21wYXJpc29uID0gY29udHJhc3RzLCBgTnVtYmVyIG9mIGdlbmVzIHdpdGggYWRqdXN0ZWQgUCA8IDAuMDVgID0gc2lncHMsCiAgICAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRikKa2FibGUoc3VtdGFiLCBhbGlnbiA9ICdjJykgJT4lIGthYmxlX3N0eWxpbmcoKSAlPiUKICBhZGRfaGVhZGVyX2Fib3ZlKGMoIk92ZXJ2aWV3IG9mIHJlc3VsdHMiID0gMiksIGZvbnRfc2l6ZSA9ICJsYXJnZXIiLCBib2xkID0gVCwgYWxpZ24gPSAibCIpCmBgYAoKIyBIZWF0bWFwcwoKYGBge3IgcmVhZHR3by13YXksIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLHdhcm5pbmc9RkFMU0V9CmNvbmRpdGlvbl9zdGF0cyA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvMTVfcHB0X3ZfMC4yX3BwdC5jc3YiLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKTSA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvMTVfcHB0X3ZfMC4yX3BwdF9NLmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSBOVUxMKQpGVyA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvMTVfcHB0X3ZfMC4yX3BwdF9GVy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IE5VTEwpCkNsYWRlM19NIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC8xNV9wcHRfdl8wLjJfcHB0X0NsYWRlM19NLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKQ2xhZGUzX0ZXIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC8xNV9wcHRfdl8wLjJfcHB0X0NsYWRlM19GVy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IE5VTEwpCkNsYWRlMl9NIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC8xNV9wcHRfdl8wLjJfcHB0X0NsYWRlMl9NLmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSBOVUxMKQpDbGFkZTJfRlcgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLzE1X3BwdF92XzAuMl9wcHRfQ2xhZGUyX0ZXLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKQ2xhZGUxX00gPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLzE1X3BwdF92XzAuMl9wcHRfQ2xhZGUxX00uY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSBOVUxMKQpDbGFkZTFfRlcgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLzE1X3BwdF92XzAuMl9wcHRfQ2xhZGUxX0ZXLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKIyBzaWcgZ2VuZXMgMTVwcHQgdnMuIDAuMnBwdApkaW0oY29uZGl0aW9uX3N0YXRzKQpjb25kaXRpb25fc2lnPC1jb25kaXRpb25fc3RhdHNbY29uZGl0aW9uX3N0YXRzJGFkai5QLlZhbCA8PSAwLjA1LF0KY29uZGl0aW9uX3NpZzwtY29uZGl0aW9uX3NpZ1shaXMubmEoY29uZGl0aW9uX3NpZyRhZGouUC5WYWwpLF0KY29uZGl0aW9uX3NpZzwtY29uZGl0aW9uX3NpZyRYCmxlbmd0aChjb25kaXRpb25fc2lnKQojIHNpZyBnZW5lcyBNIGFuZCBGVwojIHR3by13YXkKIyBjb25zZXJ2ZWQgcmVzcG9uc2UKI2RpbShNKQpNX3NpZyA8LSBNW00kYWRqLlAuVmFsIDw9IDAuMDUsXSAKTV9zaWcgPC0gTV9zaWdbIWlzLm5hKE1fc2lnJGFkai5QLlZhbCksXQpNX3NpZyA8LSBNX3NpZyRYCiNsZW5ndGgoTV9zaWcpCiNkaW0oRlcpCkZXX3NpZyA8LSBGV1tGVyRhZGouUC5WYWwgPD0gMC4wNSxdIApGV19zaWcgPC0gRldfc2lnWyFpcy5uYShGV19zaWckYWRqLlAuVmFsKSxdCkZXX3NpZyA8LSBGV19zaWckWAojbGVuZ3RoKEZXX3NpZykKYGBgCgpgYGB7ciByZWFkdGhyZWV3YXksIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFLHdhcm5pbmc9RkFMU0V9CiMgQ2xhZGUgMyAtIHNwZWNpZmljIHJlc3BvbnNlCiMgc2lnIGdlbmVzIENsYWRlIDMsIE0KIyBidXQgbm90IHNpZyBmb3IgMi13YXkKCkNsYWRlM19NX3NpZyA8LSBDbGFkZTNfTVtDbGFkZTNfTSRhZGouUC5WYWwgPD0gMC4wNSxdCkNsYWRlM19NX3NpZyA8LSBDbGFkZTNfTV9zaWdbIWlzLm5hKENsYWRlM19NX3NpZyRhZGouUC5WYWwpLF0KZGltKENsYWRlM19NX3NpZykKQ2xhZGUzX01fc2lnX3NwZWNpZmljIDwtIENsYWRlM19NX3NpZ1shQ2xhZGUzX01fc2lnJFggJWluJSBNX3NpZyxdCmRpbShDbGFkZTNfTV9zaWdfc3BlY2lmaWMpCkNsYWRlM19NX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTNfTV9zaWdfc3BlY2lmaWMkWAoKIyBDbGFkZSAzIC0gc3BlY2lmaWMgcmVzcG9uc2UKIyBzaWcgZ2VuZXMgQ2xhZGUgMSxGVwojIGJ1dCBub3Qgc2lnIGZvciAyLXdheQoKQ2xhZGUzX0ZXX3NpZyA8LSBDbGFkZTNfRldbQ2xhZGUzX0ZXJGFkai5QLlZhbCA8PSAwLjA1LF0KQ2xhZGUzX0ZXX3NpZyA8LSBDbGFkZTNfRldfc2lnWyFpcy5uYShDbGFkZTNfRldfc2lnJGFkai5QLlZhbCksXQpkaW0oQ2xhZGUzX0ZXX3NpZykKQ2xhZGUzX0ZXX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTNfRldfc2lnWyFDbGFkZTNfRldfc2lnJFggJWluJSBGV19zaWcsXQpkaW0oQ2xhZGUzX0ZXX3NpZ19zcGVjaWZpYykKQ2xhZGUzX0ZXX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTNfRldfc2lnX3NwZWNpZmljJFgKCiMgQ2xhZGUgMiAtIHNwZWNpZmljIHJlc3BvbnNlCiMgc2lnIGdlbmVzIENsYWRlIDIsIE0KIyBidXQgbm90IHNpZyBmb3IgMi13YXkKCkNsYWRlMl9NX3NpZyA8LSBDbGFkZTJfTVtDbGFkZTJfTSRhZGouUC5WYWwgPD0gMC4wNSxdCkNsYWRlMl9NX3NpZyA8LSBDbGFkZTJfTV9zaWdbIWlzLm5hKENsYWRlMl9NX3NpZyRhZGouUC5WYWwpLF0KZGltKENsYWRlMl9NX3NpZykKQ2xhZGUyX01fc2lnX3NwZWNpZmljIDwtIENsYWRlMl9NX3NpZ1shQ2xhZGUyX01fc2lnJFggJWluJSBNX3NpZyxdCmRpbShDbGFkZTJfTV9zaWdfc3BlY2lmaWMpCkNsYWRlMl9NX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTJfTV9zaWdfc3BlY2lmaWMkWAoKIyBDbGFkZSAyIC0gc3BlY2lmaWMgcmVzcG9uc2UKIyBzaWcgZ2VuZXMgQ2xhZGUgMiwgRlcKIyBidXQgbm90IHNpZyBmb3IgMi13YXkKCkNsYWRlMl9GV19zaWcgPC0gQ2xhZGUyX0ZXW0NsYWRlMl9GVyRhZGouUC5WYWwgPD0gMC4wNSxdCkNsYWRlMl9GV19zaWcgPC0gQ2xhZGUyX0ZXX3NpZ1shaXMubmEoQ2xhZGUyX0ZXX3NpZyRhZGouUC5WYWwpLF0KZGltKENsYWRlMl9GV19zaWcpCkNsYWRlMl9GV19zaWdfc3BlY2lmaWMgPC0gQ2xhZGUyX0ZXX3NpZ1shQ2xhZGUyX0ZXX3NpZyRYICVpbiUgRldfc2lnLF0KZGltKENsYWRlMl9GV19zaWdfc3BlY2lmaWMpCkNsYWRlMl9GV19zaWdfc3BlY2lmaWMgPC0gQ2xhZGUyX0ZXX3NpZ19zcGVjaWZpYyRYCgojIENsYWRlIDEgLSBzcGVjaWZpYyByZXNwb25zZQojIHNpZyBnZW5lcyBDbGFkZSAxLCBNCiMgYnV0IG5vdCBzaWcgZm9yIDItd2F5CgpDbGFkZTFfTV9zaWcgPC0gQ2xhZGUxX01bQ2xhZGUxX00kYWRqLlAuVmFsIDw9IDAuMDUsXQpDbGFkZTFfTV9zaWcgPC0gQ2xhZGUxX01fc2lnWyFpcy5uYShDbGFkZTFfTV9zaWckYWRqLlAuVmFsKSxdCmRpbShDbGFkZTFfTV9zaWcpCkNsYWRlMV9NX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTFfTV9zaWdbIUNsYWRlMV9NX3NpZyRYICVpbiUgTV9zaWcsXQpkaW0oQ2xhZGUxX01fc2lnX3NwZWNpZmljKQpDbGFkZTFfTV9zaWdfc3BlY2lmaWMgPC0gQ2xhZGUxX01fc2lnX3NwZWNpZmljJFgKCiMgQ2xhZGUgMSAtIHNwZWNpZmljIHJlc3BvbnNlCiMgc2lnIGdlbmVzIENsYWRlIDEsIEZXCiMgYnV0IG5vdCBzaWcgZm9yIDItd2F5CgpDbGFkZTFfRldfc2lnIDwtIENsYWRlMV9GV1tDbGFkZTFfRlckYWRqLlAuVmFsIDw9IDAuMDUsXQpDbGFkZTFfRldfc2lnIDwtIENsYWRlMV9GV19zaWdbIWlzLm5hKENsYWRlMV9GV19zaWckYWRqLlAuVmFsKSxdCmRpbShDbGFkZTFfRldfc2lnKQpDbGFkZTFfRldfc2lnX3NwZWNpZmljIDwtIENsYWRlMV9GV19zaWdbIUNsYWRlMV9GV19zaWckWCAlaW4lIEZXX3NpZyxdCmRpbShDbGFkZTFfRldfc2lnX3NwZWNpZmljKQpDbGFkZTFfRldfc2lnX3NwZWNpZmljIDwtIENsYWRlMV9GV19zaWdfc3BlY2lmaWMkWApgYGAKCmBgYHtyIHJlYWRub3JtY291bnRzLCByZXN1bHRzPSdoaWRlJywgaW5jbHVkZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQpub3JtX2NvdW50cyA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvbm9ybWFsaXplZF9jb3VudHMuY3N2IixzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IE5VTEwpCiNjb2xuYW1lcyhub3JtX2NvdW50cykKY29scy5ub3JtX2NvdW50cyA8LSBjb2xuYW1lcyhub3JtX2NvdW50cykKc3BlY2llc19jb25kaXRpb248LWFzLnZlY3RvcihwYXN0ZShzcGVjaWVzLGNvbmRpdGlvbixzZXA9Ii4iKSkKcm93bmFtZXMobm9ybV9jb3VudHMpIDwtIG5vcm1fY291bnRzJEVuc2VtYmwKbm9ybV9jb3VudHMgPC0gbm9ybV9jb3VudHNbLC0xXQpjb2xuYW1lcyhub3JtX2NvdW50cykgPC0gc3BlY2llc19jb25kaXRpb24KZGltKG5vcm1fY291bnRzKSAKYGBgCgpgYGB7ciBtZWFucywgcmVzdWx0cz0naGlkZScsIGluY2x1ZGU9RkFMU0Usd2FybmluZz1GQUxTRX0KbWVhbl9ub3JtX2NvdW50czwtc2FwcGx5KHVuaXF1ZShjb2xuYW1lcyhub3JtX2NvdW50cykpLCBmdW5jdGlvbihpKQogIHJvd01lYW5zKG5vcm1fY291bnRzWyxjb2xuYW1lcyhub3JtX2NvdW50cykgPT0gaV0pKQpwaCA8LSBjKCJNIiwiTSIsIk0iLCJNIiwiTSIsIk0iLCJNIiwiTSIsIk0iLCJNIiwiRlciLCJGVyIsIkZXIiwiRlciLCJNIiwiTSIsIk0iLCJNIiwiRlciLCJGVyIsIk0iLCJNIiwiTSIsIk0iLCJGVyIsIkZXIiwiRlciLCJGVyIpCmNsIDwtIGMoIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMSIsIkNsYWRlMiIsIkNsYWRlMiIsIkNsYWRlMiIsIkNsYWRlMiIsIkNsYWRlMiIsIkNsYWRlMiIsIkNsYWRlMyIsIkNsYWRlMyIsIkNsYWRlMyIsIkNsYWRlMyIsIkNsYWRlMyIsIkNsYWRlMyIsIkNsYWRlMyIsIkNsYWRlMyIpCmNvbmRpdGlvbiA8LSBjKCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIpCiAgCmNvbG5hbWVzKG1lYW5fbm9ybV9jb3VudHMpCnNhbXBsZV9vcmRlciA8LSBjKCJGX2dyYW5kaXMuMTVfcHB0IiwiRl9ncmFuZGlzLjAuMl9wcHQiLCJGX3NpbWlsaXMuMTVfcHB0IiwiRl9zaW1pbGlzLjAuMl9wcHQiLAogICAgICAgICAgICJGX2RpYXBoYW51cy4xNV9wcHQiLCJGX2RpYXBoYW51cy4wLjJfcHB0IiwiRl9oZXRlcm9jbGl0dXNNRFBMLjE1X3BwdCIsIkZfaGV0ZXJvY2xpdHVzTURQTC4wLjJfcHB0IiwKICAgICAgICAgICAiRl9oZXRlcm9jbGl0dXNNRFBQLjE1X3BwdCIsIkZfaGV0ZXJvY2xpdHVzTURQUC4wLjJfcHB0IiwiRl9jYXRhbmF0dXMuMTVfcHB0IiwiRl9jYXRhbmF0dXMuMC4yX3BwdCIsCiAgICAgICAgICAgIkZfcmF0aGJ1bmkuMTVfcHB0IiwiRl9yYXRoYnVuaS4wLjJfcHB0IiwiRl9wYXJ2YXBpbmlzLjE1X3BwdCIsIkZfcGFydmFwaW5pcy4wLjJfcHB0IiwKICAgICAgICAgICAiTF9wYXJ2YS4xNV9wcHQiLCJMX3BhcnZhLjAuMl9wcHQiLCJMX2dvb2RlaS4xNV9wcHQiLCJMX2dvb2RlaS4wLjJfcHB0IiwKICAgICAgICAgICAiRl9jaHJ5c290dXMuMTVfcHB0IiwiRl9jaHJ5c290dXMuMC4yX3BwdCIsIkFfeGVuaWNhLjE1X3BwdCIsIkFfeGVuaWNhLjAuMl9wcHQiLAogICAgICAgICAgICJGX25vdGF0dXMuMTVfcHB0IiwiRl9ub3RhdHVzLjAuMl9wcHQiLCJGX29saXZhY2VvdXMuMTVfcHB0IiwiRl9vbGl2YWNlb3VzLjAuMl9wcHQiKQoKbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkIDwtIG1lYW5fbm9ybV9jb3VudHNbLHNhbXBsZV9vcmRlcl0KCmBgYAoKCmBgYHtyIG1lYW50d293YXksIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFLHdhcm5pbmc9RkFMU0V9Cm1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9jb25kaXRpb25fc2lnIDwtIG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZFtyb3duYW1lcyhtZWFuX25vcm1fY291bnRzX29yZGVyZWQpICVpbiUgY29uZGl0aW9uX3NpZyxdCmRpbShtZWFuX25vcm1fY291bnRzX29yZGVyZWRfY29uZGl0aW9uX3NpZykKbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fc2lnIDwtIG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZFtyb3duYW1lcyhtZWFuX25vcm1fY291bnRzX29yZGVyZWQpICVpbiUgQ2xhZGUxX01fc2lnX3NwZWNpZmljLF0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX0ZXX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIEZXX3NpZyxdCm1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlMV9zaWcgPC0gbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkW3Jvd25hbWVzKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZCkgJWluJSBDbGFkZTFfTV9zaWdfc3BlY2lmaWMsXQptZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUxX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlMV9GV19zaWdfc3BlY2lmaWMgLF0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fQ2xhZGUyX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlMl9NX3NpZ19zcGVjaWZpYyAsXQptZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUyX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlMl9GV19zaWdfc3BlY2lmaWMgLF0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fQ2xhZGUzX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlM19NX3NpZ19zcGVjaWZpYyxdCm1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9GV19DbGFkZTNfc2lnIDwtIG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZFtyb3duYW1lcyhtZWFuX25vcm1fY291bnRzX29yZGVyZWQpICVpbiUgQ2xhZGUzX0ZXX3NpZ19zcGVjaWZpYyAsXQpgYGAKCiMjIE1hcmluZS1DbGFkZSAxICh0aHJlZS13YXkpIHJlc3BvbnNlCgpgYGB7ciBNQ2xhZGUxLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfTV9DbGFkZTFfc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlMV9zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyBGcmVzaHdhdGVyLUNsYWRlIDEgKHRocmVlLXdheSkgcmVzcG9uc2UKCmBgYHtyIEZXQ2xhZGUxLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUxX3NpZysxKQpnZW5lRGlzdHMgPC0gZGlzdChtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUxX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIE1hcmluZS1DbGFkZSAyICh0aHJlZS13YXkpIHJlc3BvbnNlCgpgYGB7ciBNQ2xhZGUyLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfTV9DbGFkZTJfc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlMl9zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyBGcmVzaHdhdGVyLUNsYWRlIDIgKHRocmVlLXdheSkgcmVzcG9uc2UKCmBgYHtyIEZXQ2xhZGUyLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUyX3NpZysxKQpnZW5lRGlzdHMgPC0gZGlzdChtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUyX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIE1hcmluZS1DbGFkZSAzICh0aHJlZS13YXkpIHJlc3BvbnNlCgpgYGB7ciBNQ2xhZGUzLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfTV9DbGFkZTNfc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlM19zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyBGcmVzaHdhdGVyLUNsYWRlIDMgKHRocmVlLXdheSkgcmVzcG9uc2UKCmBgYHtyIEZXQ2xhZGUzLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUzX3NpZysxKQpnZW5lRGlzdHMgPC0gZGlzdChtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUzX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIyBNYXJpbmUgcGh5c2lvbG9neSAodHdvLXdheSkgY29uc2VydmVkIHJlc3BvbnNlCgpgYGB7ciBNaGVhdG1hcCwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyksd2FybmluZz1GQUxTRX0KcmxkIDwtIGxvZzIobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIyBGcmVzaHdhdGVyIHBoeXNpb2xvZ3kgKHR3by13YXkpIGNvbnNlcnZlZCByZXNwb25zZQoKYGBge3IgRldoZWF0bWFwLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSx3YXJuaW5nPUZBTFNFfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9GV19zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyMgQ29uZGl0aW9uIHJlc3BvbnNlIChtYWluIGVmZmVjdCkKCmBgYHtyIGNvbmRpdGlvbmhlYXRtYXAsIGZpZy5rZWVwPSJsYXN0IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpLHdhcm5pbmc9RkFMU0V9CnJsZCA8LSBsb2cyKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9jb25kaXRpb25fc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9jb25kaXRpb25fc2lnKQpkZiA8LSBkYXRhLmZyYW1lKHBoLGNsLCBjb25kaXRpb24sc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKcm93bmFtZXMoZGYpIDwtIGNvbG5hbWVzKHJsZCkKcGhlYXRtYXAocmxkLCBzaG93X3Jvd25hbWVzPUZBTFNFLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBnZW5lRGlzdHMsIGNsdXN0ZXJfY29scz0gRkFMU0UsYW5ub3RhdGlvbl9jb2w9ZGYpCmBgYAoKYGBge3IgcGFja2FnZXN9CgpzZXNzaW9uSW5mbygpCgpgYGA=